document.getElementById('scanButton').addEventListener('click', scanDevices);

async function scanDevices() {
    if (!navigator.bluetooth) {
        console.log('Web Bluetooth API is not available in your browser!');
        return;
    }

    try {
        const device = await navigator.bluetooth.requestDevice({
            acceptAllDevices: true,
            optionalServices: ['battery_service', 'device_information', 0x1800, 0x1801, 0x1802, 0x1803, 0x1804, 0x1805, 0x1806, 0x1807, 0x1808, 0x1809, 0x180A, 0x180B, 0x180C, 0x180D, 0x180E, 0x180F, 0x1810, 0x1811, 0x1812, 0x1813, 0x1814, 0x1815, 0x1816, 0x1817, 0x1818, 0x1819, 0x181A, 0x181B, 0x181C, 0x181D, 0x181E, 0x181F, '6e400009-b5a3-f393-e0a9-e50e24dcca9e']
        });
        
        console.log('Found device:', device.name);
        const deviceItem = addDeviceToList(device.name || 'Unknown device');

        // Connect to the device
        try {
            const server = await device.gatt.connect();
            console.log('Connected to the device');

            // Get all services
            try {
                const services = await server.getPrimaryServices();
                console.log('Got primary services');

                if (services.length === 0) {
                    console.log('No services found');
                    addServiceToList(deviceItem, 'No services found');
                } else {
                    for (const service of services) {
                        console.log('Service:', service.uuid);
                        const serviceItem = addServiceToList(deviceItem, service.uuid);

                        // Get all characteristics for this service
                        const characteristics = await service.getCharacteristics();

                        if (characteristics.length === 0) {
                            console.log('No characteristics found for this service');
                            addCharacteristicToList(serviceItem, 'No characteristics found');
                        } else {
                            for (const characteristic of characteristics) {
                                console.log('Characteristic:', characteristic.uuid);
                                addCharacteristicToList(serviceItem, characteristic);
                            }
                        }
                    }
                }
            } catch (error) {
                console.error('Error getting services:', error);
                addServiceToList(deviceItem, 'Error getting services: ' + error.message);
            }
        } catch (error) {
            console.error('Error connecting to the device:', error);
            addServiceToList(deviceItem, 'Error connecting to the device: ' + error.message);
        }
    } catch (error) {
        console.error('Error:', error);
    }
}

function addDeviceToList(deviceName) {
    const list = document.getElementById('deviceList');
    const item = document.createElement('li');
    const deviceHeader = document.createElement('div');
    deviceHeader.textContent = deviceName;
    deviceHeader.style.fontWeight = 'bold';
    item.appendChild(deviceHeader);
    list.appendChild(item);
    return item;
}

function addServiceToList(deviceItem, serviceUuid) {
    const serviceList = deviceItem.querySelector('ul') || document.createElement('ul');
    serviceList.style.paddingLeft = '20px';
    const serviceItem = document.createElement('li');
    serviceItem.textContent = 'Service: ' + serviceUuid;
    serviceList.appendChild(serviceItem);
    deviceItem.appendChild(serviceList);
    return serviceItem;
}

function addCharacteristicToList(serviceItem, characteristic) {
    const characteristicList = serviceItem.querySelector('ul') || document.createElement('ul');
    characteristicList.style.paddingLeft = '20px';
    const characteristicItem = document.createElement('li');
    
    let characteristicName = getCharacteristicName(characteristic.uuid);
    let properties = getCharacteristicProperties(characteristic);
    
    characteristicItem.textContent = `Characteristic: ${characteristicName} (${characteristic.uuid})`;
    characteristicItem.title = `Properties: ${properties.join(', ')}`;
    
    const operations = getCharacteristicOperations(characteristic);
    if (operations.length > 0) {
        const operationsContainer = document.createElement('div');
        operationsContainer.style.marginTop = '5px';
        operations.forEach(operation => {
            const operationButton = document.createElement('button');
            operationButton.textContent = operation;
            operationButton.onclick = () => handleCharacteristicOperation(characteristic, operation);
            operationButton.style.marginRight = '5px';
            operationButton.style.marginBottom = '5px';
            operationsContainer.appendChild(operationButton);
        });
        characteristicItem.appendChild(operationsContainer);
    } else {
        const noOperationsSpan = document.createElement('span');
        noOperationsSpan.textContent = 'No available operations';
        characteristicItem.appendChild(noOperationsSpan);
    }
    
    characteristicList.appendChild(characteristicItem);
    serviceItem.appendChild(characteristicList);
}

function handleCharacteristicOperation(characteristic, operation) {
    switch (operation) {
        case 'Read':
            readCharacteristic(characteristic);
            break;
        case 'Write':
        case 'Write Without Response':
            writeCharacteristic(characteristic, operation);
            break;
        case 'Start Notifications':
            startNotifications(characteristic);
            break;
        case 'Stop Notifications':
            stopNotifications(characteristic);
            break;
    }
}

async function readCharacteristic(characteristic) {
    try {
        const value = await characteristic.readValue();
        displayMessage(`Read value: ${new TextDecoder().decode(value)}`);
    } catch (error) {
        displayMessage(`Error reading characteristic: ${error}`);
    }
}

async function writeCharacteristic(characteristic, operation) {
    const message = document.getElementById('messageInput').value;
    if (!message) {
        displayMessage('Please enter a message to send');
        return;
    }
    try {
        const encoder = new TextEncoder();
        const value = encoder.encode(message);
        if (operation === 'Write') {
            await characteristic.writeValue(value);
        } else {
            await characteristic.writeValueWithoutResponse(value);
        }
        displayMessage(`Sent message: ${message}`);
    } catch (error) {
        displayMessage(`Error writing to characteristic: ${error}`);
    }
}

function startNotifications(characteristic) {
    characteristic.startNotifications()
        .then(() => {
            displayMessage('Notifications started');
            characteristic.addEventListener('characteristicvaluechanged', handleCharacteristicValueChanged);
        })
        .catch(error => displayMessage(`Error starting notifications: ${error}`));
}

function stopNotifications(characteristic) {
    characteristic.stopNotifications()
        .then(() => {
            displayMessage('Notifications stopped');
            characteristic.removeEventListener('characteristicvaluechanged', handleCharacteristicValueChanged);
        })
        .catch(error => displayMessage(`Error stopping notifications: ${error}`));
}

function handleCharacteristicValueChanged(event) {
    const value = event.target.value;
    displayMessage(`Notification received: ${new TextDecoder().decode(value)}`);
}

function displayMessage(message) {
    const messageBox = document.getElementById('messageBox');
    messageBox.value += message + '\n';
    messageBox.scrollTop = messageBox.scrollHeight;
}

document.getElementById('sendButton').addEventListener('click', () => {
    const messageInput = document.getElementById('messageInput');
    if (messageInput.value.trim() !== '') {
        displayMessage('Please select a characteristic to write to');
        messageInput.value = '';
    }
});

function getCharacteristicName(uuid) {
    const characteristicNames = {
        '2a00': 'Device Name',
        '2a01': 'Appearance',
        '2a02': 'Peripheral Privacy Flag',
        '2a03': 'Reconnection Address',
        '2a04': 'Peripheral Preferred Connection Parameters',
        '2a05': 'Service Changed',
        '2a06': 'Alert Level',
        '2a07': 'Tx Power Level',
        '2a08': 'Date Time',
        '2a09': 'Day of Week',
        '2a0a': 'Day Date Time',
        // 添加更多已知的特性名称
    };
    return characteristicNames[uuid.toLowerCase().substr(4)] || 'Unknown Characteristic';
}

function getCharacteristicProperties(characteristic) {
    const properties = [];
    if (characteristic.properties.read) properties.push('Read');
    if (characteristic.properties.write) properties.push('Write');
    if (characteristic.properties.writeWithoutResponse) properties.push('Write Without Response');
    if (characteristic.properties.notify) properties.push('Notify');
    if (characteristic.properties.indicate) properties.push('Indicate');
    if (characteristic.properties.authenticatedSignedWrites) properties.push('Authenticated Signed Writes');
    if (characteristic.properties.reliableWrite) properties.push('Reliable Write');
    if (characteristic.properties.writableAuxiliaries) properties.push('Writable Auxiliaries');
    return properties;
}

function getCharacteristicOperations(characteristic) {
    const operations = [];
    if (characteristic.properties.read) operations.push('Read');
    if (characteristic.properties.write) operations.push('Write');
    if (characteristic.properties.writeWithoutResponse) operations.push('Write Without Response');
    if (characteristic.properties.notify) operations.push('Start Notifications');
    if (characteristic.properties.indicate) operations.push('Start Indications');
    return operations;
}
